<?php

class Wlib_Controller_Action_Helper_AclMvc extends Zend_Controller_Action_Helper_Abstract
{
    const EXCEPTION_ACLMVC_ACCES_DENIED = 'EXCEPTION_ACLMVC_ACCES_DENIED';

    protected $_aclMvcManager = null;
    
    protected $_accesDeniedPageRequestParams = array(
        'module' => 'default',
        'controller' => 'error',
        'action' => 'error'
    );

    protected $_loginPageRequestParams = array(
        'module' => 'default',
        'controller' => 'auth',
        'action' => 'index'
    );
    
    public function preDispatch()
    {
        $aclMvcManager = $this->getAclMvcManager();
        $this->getActionController()->view->aclMvcManager = $aclMvcManager;

        $this->_checkAccess();
    }

    protected function _checkAccess()
    {
        $aclMvcManager = $this->getAclMvcManager();

        $request = $this->getActionController()->getRequest();
        $routeParams = array(
            'action' => $request->getActionName(),
            'controller' => $request->getControllerName(),
            'module' => $request->getModuleName(),
        );

        if(!$aclMvcManager->isControllerActionAllowed($routeParams)) {
            if(!$aclMvcManager->getAuthIdentity()) {
                $this->_setRequestToLoginPage($request);
            } else {
                $this->_setRequestToAccesDeniedPage($request);
            }

            $request->setDispatched(false);
        }
    }

    protected function _setRequestToLoginPage($request)
    {
        $request->setModuleName($this->_loginPageRequestParams['module'])
                ->setControllerName($this->_loginPageRequestParams['controller'])
                ->setActionName($this->_loginPageRequestParams['action']);
    }

    protected function _setRequestToAccesDeniedPage($request)
    {
        $exception = new Wlib_Controller_Action_Helper_AclMvcException('Access Denied');

        $error = new ArrayObject(array(), ArrayObject::ARRAY_AS_PROPS);
        $error->exception = $exception;
        $error->type = self::EXCEPTION_ACLMVC_ACCES_DENIED;
        $error->request = clone $request;

        $request->setParam('error_handler', $error)
                ->setModuleName($this->_accesDeniedPageRequestParams['module'])
                ->setControllerName($this->_accesDeniedPageRequestParams['controller'])
                ->setActionName($this->_accesDeniedPageRequestParams['action']);
    }

    public function getAccesDeniedPageRequestParams()
    {
        return $this->_accesDeniedPageRequestParams;
    }

    public function setAccesDeniedPageRequestParams($accesDeniedPageRequestParams)
    {
        $this->_accesDeniedPageRequestParams = $accesDeniedPageRequestParams;
        return $this;
    }

    /**
     * @return Wlib_Acl_AclMvcManager
     */
    public function getAclMvcManager()
    {
        return $this->_aclMvcManager;
    }

    public function setAclMvcManager($aclMvcManager)
    {
        $this->_aclMvcManager = $aclMvcManager;
        return $this;
    }
}
